#include "seckeyshm.h"
#include <QDebug>
#include <string.h>

SeckeyShm::SeckeyShm(QString key, int maxNode, QObject* parent) :
    QObject(parent)
{
    QString log;
    qDebug() << "共享内存构造函数, 参数key: " << key << "maxNode: " << maxNode;
    m_shm = new QSharedMemory(key);
    if(maxNode > 0)
    {
        m_maxNode = maxNode;
        // 创建共享内存
        log = QString("创建共享内存, 大小为: %1").arg(maxNode * sizeof(SeckeyInfo));
        qDebug() << log;
        m_shm->create(maxNode * sizeof(SeckeyInfo));
    }
    if(!m_shm->isAttached())
    {
        qDebug() << "共享内存没有关联成功, 尝试关联...";
        bool bl = m_shm->attach();
        if(!bl)
        {
            log = QString("共享内存关联状态失败, 原因: %1").arg(m_shm->errorString());
            qDebug() << log;
        }
        qDebug() << "共享内存关联成功, 恭喜!!!";
    }
    else
    {
        log = "共享内存关联成功, 恭喜!!!";
        qDebug() << log;
        if(maxNode == -1)
        {
            m_maxNode = m_shm->size() / sizeof(SeckeyInfo);
            qDebug() << "计算共享内存节点个数: " << m_maxNode;
        }
    }
}

SeckeyShm::~SeckeyShm()
{
    m_shm->detach();
    delete m_shm;
}

void SeckeyShm::initShm()
{
    void* data = m_shm->data();
    // 内存初始化为0
    memset(data, 0, m_shm->size());
}

bool SeckeyShm::writeShm(SeckeyInfo& info)
{
    bool ret = true;
    // 关联共享内存
    SeckeyInfo* pAddr = static_cast<SeckeyInfo*>(m_shm->data());
    if (pAddr == NULL)
    {
        ret = false;
        return ret;
    }

    // 共享内存加锁
    m_shm->lock();

    // 判断传入的网点密钥是否已经存在
    SeckeyInfo	*pNode = NULL;
    for (int i = 0; i < m_maxNode; i++)
    {
        qDebug() << "当前是共享内存的第 " << i << " 个节点";
        // pNode依次指向每个节点的首地址
        pNode = pAddr + i;
        if (strcmp(pNode->clientID, info.clientID) == 0 &&
                strcmp(pNode->serverID, info.serverID) == 0)
        {
            // 如果找到了该网点秘钥已经存在, 使用新秘钥覆盖旧的值
            *pNode = info;
            qDebug() << "写数据成功: 原数据被覆盖!" << endl;
            m_shm->unlock();
            return ret;
        }
    }

    // 若没有找到对应的信息, 找一个空节点将秘钥信息写入
    int i = 0;
    SeckeyInfo tmp; //空结点
    for (i = 0; i < m_maxNode; i++)
    {
        pNode = pAddr + i;
        if (tmp == *pNode)
        {
            *pNode = info;
            qDebug() << "写数据成功: 在新的节点上添加数据!" << endl;
            break;
        }
    }
    m_shm->unlock();
    if (i == m_maxNode)
    {
        ret = false;
    }

    return ret;
}

SeckeyInfo SeckeyShm::readShm(QString clientID, QString serverID)
{
    SeckeyInfo *pAddr = static_cast<SeckeyInfo*>(m_shm->data());
    if (pAddr == NULL)
    {
        qDebug() << "共享内存关联失败, 未读到数据...";
        return SeckeyInfo();
    }

    //遍历网点信息
    SeckeyInfo info, *pNode = NULL;
    // 通过clientID和serverID查找节点
    qDebug() << "maxNode: " << m_maxNode << endl;
    m_shm->lock();
    for (int i = 0; i < m_maxNode; i++)
    {
        pNode = pAddr + i;
        if (QString(pNode->clientID) == clientID &&
                QString(pNode->serverID) ==  serverID)
        {
            qDebug() << "当前节点编号: " << i;
            // 找到的节点信息, 赋值给传出参数
            info = *pNode;
            break;
        }
    }
    m_shm->unlock();
    QString msg = QString("状态: %1, keyID: %2, clientid: %3, serverid: %4, key: %5")
            .arg(info.status).arg(info.seckeyID).arg(info.clientID)
            .arg(info.serverID).arg(info.seckey);
    qDebug() << msg;
    return info;
}

SeckeyInfo SeckeyShm::readShm(int keyID)
{
    m_shm->lock();
    SeckeyInfo *pAddr = static_cast<SeckeyInfo*>(m_shm->data());
    if (pAddr == NULL)
    {
        qDebug() << "共享内存关联失败, 未读到数据...";
        m_shm->unlock();
        return SeckeyInfo();
    }

    //遍历网点信息
    SeckeyInfo info, *pNode = NULL;
    // 通过clientID和serverID查找节点
    qDebug() << "当前要查找的keyID: " << keyID;
    qDebug() << "maxNode: " << m_maxNode;
    for (int i = 0; i < m_maxNode; i++)
    {
        pNode = pAddr + i;
        if (keyID == pNode->seckeyID)
        {
            // 找到的节点信息, 拷贝到传出参数
            info = *pNode;
            break;
        }
    }
    m_shm->unlock();
    return info;
}
